package controller;

import java.sql.Timestamp;
import java.util.List;
import model.ArtikelFilm;
import model.Datadrager;
import model.Genre;
import model.Klant;
import model.Medewerker;
import model.Reservering;
import model.Uitvoering;
import org.joda.time.DateTime;

/**
 * Met deze klasse hebben we een controller laag aangebracht tussen de view en
 * de persistentie laag. Dit vereenvoudigd de koppelbaarheid, maakt het
 * makkelijk uitbreidbaar en verhoogd de onderhoudbaarheid.
 *
 */
public class ControlPanel {

    private final int vestigingID = 1;
    private DatabaseController dbc = null;

    public ControlPanel() {
        dbc = new DatabaseController();
        dbc.createTables();
    }

    /**
     * Methode om de login credentials te controleren.
     *
     * @param username
     * @param password
     * @return
     */
    public boolean controleerLogin(String username, String password) {
        return dbc.controleerLogin(username, password);
    }

    /**
     * Methode om een nieuwe klant toe te voegen aan de database.
     *
     * @param k
     * @return
     */
    public boolean toevoegenKlant(Klant k) {
        boolean result = false;
        int nextHighestKlantnummer = dbc.getHighestKlantnummer();
        nextHighestKlantnummer++;
        result = dbc.insertKlant(this.vestigingID, nextHighestKlantnummer,
                k.getNaam(), k.getAchternaam(), k.getStraat(), k.getHuisnummer(),
                k.getTelefoonnummer(), k.getWoonplaats(),
                k.getLoginAccount().getAccountnaam(),
                k.getLoginAccount().getWachtwoord());
        return result;
    }

    /**
     * Methode om een nieuwe werknemer toe te voegen. Op dit moment is deze
     * methode nog niet geimplementeerd in de view laag.
     *
     * @param m
     */
    public void toevoegenMedewerker(Medewerker m) {
        dbc.insertMedewerker(this.vestigingID, m.getPersoneelsnummer(),
                m.getLoginAccount().getAccountnaam(),
                m.getLoginAccount().getWachtwoord(), m.getIsadmin());
    }

    /**
     * Methode om een nieuwe vestiging toe te voegen aan de database. Op dit
     * moment is deze methode nog niet geimplementeerd in de view laag.
     *
     * @param plaats
     * @param adres
     */
    public void toevoegenVestiging(String plaats, String adres) {
        dbc.insertVestiging(plaats, adres);
    }

    /**
     * Methode om in de database te kunnen zoeken op artikelnummer.
     *
     * @param artikelnummer
     * @return
     */
    public ArtikelFilm zoekenOpArtikelnummer(int artikelnummer) {
        return dbc.zoekenOpArtikelnummer(artikelnummer);
    }

    /**
     * Methode om in de database het artikel met hetzelfde artikelnummer te
     * kunnen updaten.
     *
     * @param artikelFilm
     * @return true als er een update heeft plaatsgevonden
     */
    public boolean updateArtikelFilm(ArtikelFilm artikelFilm) {
        return dbc.updateArtikelFilm(artikelFilm);
    }

    /**
     * Methode heeft verschillende parameters die ook leeg verstuurd kunnen
     * worden. De methode zal zoeken op de parameters die ingevuld zijn.
     *
     * @param artikelnummer
     * @param producent
     * @param titel
     * @param datadrager
     * @param uitvoering
     * @param genre
     * @return
     */
    public List<ArtikelFilm> getAlleMatchesArtikel(String artikelnummer, String producent, String titel,
            Datadrager datadrager, Uitvoering uitvoering, Genre genre) {
        return dbc.getAlleMatchesArtikel(artikelnummer, producent, titel, datadrager, uitvoering, genre);
    }

    /**
     * Methode om in database te achterhalen of een artikel zijn status op
     * gereserveerd staat of niet.
     *
     * @param artikelnummer
     * @return
     */
    public boolean getReservingStatus(int artikelnummer) {
        return dbc.getReservingStatus(artikelnummer);
    }

    /**
     * Methode zoekt in database alle reserveringen die bij klantnummer van
     * Klant object horen.
     *
     * @param klant
     * @return
     */
    public List<Reservering> zoekReserveringenBijKlant(Klant klant) {
        return dbc.zoekReserveringenBijKlant(klant);
    }

    /**
     * Methode die de datum ophaalt waarop een artikel met reserveringnummer
     * gereserveerd is.
     *
     * @param reserveringnr
     * @return
     */
    public String zoekGereserveerdOp(int reserveringnr) {
        return dbc.zoekGereserveerdOp(reserveringnr);
    }

    /**
     * Methode die een klant als parameter mee stuurt om niet overeenkomende
     * velden in de database te overschrijven.
     *
     * @param klant
     * @return
     */
    public boolean aanpassenKlant(Klant klant) {
        return dbc.aanpassenKlant(klant);
    }

    /**
     * Methode gebruikt klantnummer om het database record op te zoeken die
     * verwijderd dient te worden.
     *
     * @param klantnr
     * @return
     */
    public boolean verwijderenKlant(int klantnr) {
        return dbc.verwijderenKlant(klantnr);
    }

    /**
     * Methode zoekt naar klanten met gegevens die overeenkomen met de
     * verschillende parameters die ook leeg verstuurd kunnen worden. De methode
     * zal zoeken op de parameters die ingevuld zijn.
     *
     * @param klantnummer
     * @param achternaam
     * @param straatnaam
     * @param telefoonnummer
     * @return Lijst met klanten aangezien er meerdere resultaten kunnen zijn.
     */
    public List<Klant> zoekenOpKlantgegevens(int klantnummer, String achternaam, String straatnaam, String telefoonnummer) {
        return dbc.zoekenOpKlantgegevens(klantnummer, achternaam, straatnaam, telefoonnummer);
    }

    /**
     * Methode zoekt op klant in database met klantnummer als parameter.
     *
     * @param klantnummer
     * @return Klant object aangezien klantnummer uniek is.
     */
    public Klant zoekOpKlantnr(int klantnummer) {
        return dbc.zoekOpKlantnr(klantnummer);
    }

    /**
     * Methode zoekt in database op vestigingnummer. Methode heeft momenteel
     * geen parameter omdat er in de ontwikkelfase gekozen is voor 1 vestiging.
     *
     * @return
     */
    public boolean zoekOpVestigingnr() {
        return dbc.zoekOpVestigingnr();
    }

    /**
     * Methode achterhaalt het hoogstbekende artikelnummer. Berekent meteen het
     * nieuwe artikelnummer dat toegewezen kan worden.
     *
     * @return
     */
    public int verkrijgHoogsteArtikelnummer() {
        int nextArtikelnummer = dbc.getHighestArtikelnummer();
        nextArtikelnummer++;
        return nextArtikelnummer;
    }

    /**
     * Methode achterhaalt het hoogstbekende klantnummer. Berekent meteen het
     * nieuwe klantnummer dat toegewezen kan worden.
     *
     * @return
     */
    public int verkrijgHoogsteKlantnummer() {
        int nextKlantnr = dbc.getHighestKlantnummer();
        nextKlantnr++;
        return nextKlantnr;
    }

    /**
     * Methode controleert of het artikel met artikelnummer niet al gereserveerd
     * is.
     *
     * @param artikelnummer
     * @return Verstrijkdag van reservering
     */
    public DateTime controleerAanwezigheid(int artikelnummer) {
        DateTime verstrijkdatum = null;
        verstrijkdatum = dbc.controleerAanwezigheid(artikelnummer);
        return verstrijkdatum;
    }

    /**
     * Methode verwerkt verhuur opdracht.
     *
     * @param klantnr
     * @param artikelnr
     * @param verhuurdatum Datum waarop het artikel verhuurt wordt.
     * @param verstrijkDatum Datum waarop het artikel terug verwacht wordt.
     * @return true als het gelukt is om de verhuring in database te verwerken.
     */
    public boolean verhurenArtikel(int klantnr, int artikelnr, java.sql.Date verhuurdatum, java.sql.Date verstrijkDatum) {
        return dbc.verhurenArtikel(klantnr, artikelnr, verhuurdatum, verstrijkDatum);
    }

    /**
     * Artikel wordt hiermee verwijderd uit de database. Eerst wordt
     * innemenArtikel() uitgevoerd om te controleren of artikel te laat is
     * teruggebracht.
     *
     * @param klantnummer
     * @param artikelnummer
     * @return
     */
    public boolean innemenArtikel(int klantnummer, int artikelnummer) {
        return dbc.innemenArtikel(klantnummer, artikelnummer);
    }

    /**
     * Als artikel te laat wordt ingeleverd moet er een boete aan gekoppeld
     * zijn. Deze is ter illustratie uitgeschreven en bedraagt 1 euro per dag.
     *
     * @param klantnummer
     * @param artikelnummer
     * @return
     */
    public int controleerDagenTeLaat(int klantnummer, int artikelnummer) {
        int dagenTeLaat = dbc.controleerDagenTeLaat(klantnummer, artikelnummer);
        int boete = dagenTeLaat * 1;
        return boete;
    }

    /**
     * Methode om artikel toe te voegen aan database.
     *
     * @param a
     * @return gegenereerde artikelnummervan artikel
     */
    public int toevoegenArtikel(ArtikelFilm a) {
        return dbc.insertArtikel(a);
    }

    /**
     * Haalt het aantal op uit de gecreerde View Artikel_View
     *
     * @param titel
     * @param datadrager
     * @param uitvoering
     * @return aantal van artikel met criteria datadrager, uitvoering en titel.
     */
    public int zoekArtikelFilmAantal(String titel, Datadrager datadrager, Uitvoering uitvoering) {
        return dbc.getArtikelAantal(titel, datadrager, uitvoering);
    }

    /**
     * Methode om te controleren of reservering nog actueel is.
     *
     * @param artikelnummer
     * @return true als artikel weer beschikbaar is.
     */
    public boolean controleerReservering(int artikelnummer) {
        boolean available = false;
        DateTime gereserveerdOp = null;
        gereserveerdOp = dbc.controleerOpReservering(artikelnummer);

        if (gereserveerdOp != null) {
            DateTime reserveringVerstrijktop = gereserveerdOp.plusDays(1);

            if (reserveringVerstrijktop.isAfterNow()) {
                available = false;
            } else {
                available = true;
            }
        } else {
            available = true;
        }
        return available;

    }

    /**
     * Methode om reservering te maken met een timestamp van de huidige tijd.
     *
     * @param artikelnummer
     * @param klantid
     * @param date
     * @return true als dit gelukt is.
     */
    public boolean maakReservering(int artikelnummer, int klantid, Timestamp date) {
        return dbc.maakReservering(artikelnummer, klantid, date);
    }

    /**
     * Methode om een reservering op te heffen.
     *
     * @param klantnr
     * @param artikelnr
     * @param reserveringID
     * @return
     */
    public boolean annulerenReservering(int klantnr, int artikelnr, int reserveringID) {
        return dbc.annulerenReservering(klantnr, artikelnr, reserveringID);
    }

    /**
     * Methode om een Lijst met alle ArtikelFilm artikelen te krijgen die klant
     * op dit moment in zijn bezit heeft.
     *
     * @param klantnr
     * @return
     */
    public List<ArtikelFilm> zoekGehuurdDoorKlant(int klantnr) {
        return dbc.zoekGehuurdDoorKlant(klantnr);
    }

    /**
     * Methode om datum te achterhalen tot wanneer klant een artikel in zijn
     * bezit mag hebben.
     *
     * @param klantnr
     * @return datum waarop artikelfilm terug moet komen.
     */
    public java.sql.Date zoekGehuurdTot(int klantnr) {
        return dbc.zoekGehuurdTot(klantnr);
    }

    /**
     * Methode om vestigingID van deze vestiging te verkrijgen.
     *
     * @return
     */
    public int getVestigingID() {
        return vestigingID;
    }

    /**
     * Methode om het artikel te verhuren waarop klant een reservering heeft
     * gemaakt.
     *
     * @param klantnr
     * @param artikelnr
     * @param reserveringid
     * @param verhuurdatum
     * @param verstrijkDatum
     * @return
     */
    public boolean verhuurGereserveerdArtikel(int klantnr, int artikelnr, int reserveringid, java.sql.Date verhuurdatum, java.sql.Date verstrijkDatum) {
        return dbc.verhuurGereserveerdArtikel(klantnr, artikelnr, reserveringid, verhuurdatum, verstrijkDatum);
    }

    /**
     * Methode om te achterhalen of klant films in zijn bezit heeft. Als dit
     * niet het geval is mag klant gewoon een film huren.
     *
     * @param klantnr
     * @return
     */
    public boolean getVerhuurStatus(int klantnr) {
        return dbc.getVerhuurStatus(klantnr);
    }

    /**
     * Methode om de verstrijkdatum te achterhalen van een verhuurd artikel
     *
     * @param artikelnr
     * @return datum van verhuurverstrijking
     */
    public String zoekVerstrijkDatum(int artikelnr) {
        return dbc.zoekVerstrijkDatum(artikelnr);
    }

    /**
     * Methode om te achterhalen tot wanneer een artikel gereserveerd is.
     * @param artikelnr
     * @return Datum waarop reservering geplaatst is.
     */
    public java.sql.Date zoekGereserveerdTot(int artikelnr) {
        return dbc.zoekGereserveerdTot(artikelnr);
    }

    /**
     * Methode die vanuit aparte Thread uitgevoerd wordt om aflopende 
     * reserveringen automatisch te verwijderen.
     * @return True als er een reservering is verwijderd.
     */
    public boolean checkReserveringsTijden() {
        return dbc.checkReserveringsTijden();
    }

}
